package servidor.so;

import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import servidor.controladorsistema.so.SOControladorSistemaEntrada;
import servidor.gerenciadorsalasjogo.so.SOGerenciadorSalasJogoEntrada;

import comum.rn.RNDescricaoSalaJogo;
import comum.rn.RNEstatisticas;
import comum.rn.RNInfoSalaJogo;
import comum.rn.RNJogada;
import comum.rn.RNPeca;
import comum.so.SOClienteEntrada;
import comum.so.exception.FalhaComunicacaoBancoDadosException;
import comum.so.exception.FalhaValidacaoException;
import comum.so.exception.JaExistePerfilCadastradoComEsseLoginException;
import comum.so.exception.LoginEmUsoException;
import comum.so.exception.SalaCheiaException;
import comum.so.exception.SalaComNomeJaExistenteException;
import comum.so.exception.SalaNaoExisteException;
import comum.so.exception.SenhaIncorretaException;

public class SOServidorSaidaImpl implements SOServidorSaida {

	private Map<String, SOClienteEntrada> clientesEntrada;

	private SOControladorSistemaEntrada controladorSistemaEntrada;
	private SOGerenciadorSalasJogoEntrada gerenciadorSalasJogoEntrada;

	public SOServidorSaidaImpl(
			SOControladorSistemaEntrada controladorSistemaEntrada,
			SOGerenciadorSalasJogoEntrada gerenciadorSalasJogoEntrada)
			throws RemoteException {
		super();
		this.setControladorSistemaEntrada(controladorSistemaEntrada);
		this.setGerenciadorSalasJogoEntrada(gerenciadorSalasJogoEntrada);
		setClientesEntrada(new HashMap<String, SOClienteEntrada>());
	}

	@Override
	public void fazerLogin(String identificador, String senha,
			SOClienteEntrada clienteEntrada) throws RemoteException,
			FalhaValidacaoException, LoginEmUsoException,
			FalhaComunicacaoBancoDadosException {
		getControladorSistemaEntrada().validarLogin(identificador, senha);
		getClientesEntrada().put(identificador, clienteEntrada);
	}

	@Override
	public void cadastrarNovoPerfil(String identificador, String senha,
			SOClienteEntrada clienteEntrada) throws RemoteException,
			JaExistePerfilCadastradoComEsseLoginException {
		getControladorSistemaEntrada().cadastrarNovoPerfil(identificador, senha);
		getClientesEntrada().put(identificador, clienteEntrada);
	}

	@Override
	public void deslogar(String identificador) throws RemoteException {
		getControladorSistemaEntrada().deslogar(identificador);
	}

	@Override
	public List<RNDescricaoSalaJogo> buscarSalasJogo(boolean mostrarCheios,
			boolean mostrarComSenha) throws RemoteException {
		return getGerenciadorSalasJogoEntrada().buscarSalasJogo(mostrarCheios,
				mostrarComSenha);
	}

	@Override
	public RNInfoSalaJogo entrarSalaJogo(String identificador, Long idSalaJogo,
			String senha) throws RemoteException, SalaCheiaException,
			SalaNaoExisteException, SenhaIncorretaException {
		return getGerenciadorSalasJogoEntrada().entrarSalaJogo(identificador,
				idSalaJogo, senha);
	}

	@Override
	public RNInfoSalaJogo criarSalaJogo(String nome, String senha,
			String identificador) throws RemoteException,
			SalaComNomeJaExistenteException {
		return getGerenciadorSalasJogoEntrada().criarSalaJogo(nome, senha,
				identificador);
	}

	@Override
	public RNEstatisticas obterEstatisticas(String identificador)
			throws RemoteException {
		return getControladorSistemaEntrada().obterEstatisticas(identificador);
	}

	@Override
	public void sairSalaEspera(Long idSalaJogo, String identificador)
			throws RemoteException {
		getGerenciadorSalasJogoEntrada().sairSalaEspera(idSalaJogo, identificador);

	}

	@Override
	public boolean entrarMesa(int posicaoDesejada, Long idSalaJogo,
			String identificador) throws RemoteException {
		return getGerenciadorSalasJogoEntrada().entrarMesa(posicaoDesejada,
				idSalaJogo, identificador);
	}

	@Override
	public void sairMesa(Long idSalaJogo, String identificador)
			throws RemoteException {
		getGerenciadorSalasJogoEntrada().sairMesa(idSalaJogo, identificador);
	}

	@Override
	public void fazerJogada(String jogadorQueJogou, Long idSalaJogo,
			RNJogada jogada) {
		getGerenciadorSalasJogoEntrada().fazerJogada(jogadorQueJogou, idSalaJogo,
				jogada);
	}

	@Override
	public void informarEntradaJogador(String jogadorRecebe,
			String jogadorQueEntrou, RNInfoSalaJogo infoSalaJogo)
			throws RemoteException {
		getClientesEntrada().get(jogadorRecebe).informarEntradaJogador(
				jogadorQueEntrou, infoSalaJogo);
	}

	@Override
	public void informarSaidaJogador(String jogadorRecebe,
			String jogadorQueSaiu, RNInfoSalaJogo infoSalaJogo)
			throws RemoteException {
		getClientesEntrada().get(jogadorRecebe).informarSaidaJogador(
				jogadorQueSaiu, infoSalaJogo);
	}

	@Override
	public void informarMudancaMesa(String jogadorRecebe, Integer[] posicoesMesa)
			throws RemoteException {
		getClientesEntrada().get(jogadorRecebe).informarMudancaMesa(
				posicoesMesa);
	}

	@Override
	public void informarJogada(String jogadorRecebe, String jogadorQueJogou,
			RNJogada jogada, String novoJogadorEmTurno) throws RemoteException {
		getClientesEntrada().get(jogadorRecebe).informarJogada(jogadorQueJogou,
				jogada, novoJogadorEmTurno);
	}

	@Override
	public void informarInicioPartida(String jogadorQueRecebe,
			List<RNPeca> pecas, String primeiroAJogar) throws RemoteException {
		getClientesEntrada().get(jogadorQueRecebe).informarInicioPartida(pecas,
				primeiroAJogar);
	}

	@Override
	public void informarFimPartida(String jogadorRecebe, String mensagem)
			throws RemoteException {
		getClientesEntrada().get(jogadorRecebe).informarFimPartida(mensagem);
	}

	@Override
	public void informarFechamentoServidor() throws RemoteException {

		for (SOClienteEntrada clienteEntrada : clientesEntrada.values()) {
			try {
				clienteEntrada.informarFechamentoServidor();
			} catch (RemoteException e) {
				
			}
		}
	}

	@Override
	public void desistirJogo(Long idSalaJogo, String identificador)
			throws RemoteException {
		getGerenciadorSalasJogoEntrada().desistirJogo(idSalaJogo, identificador);

	}

	@Override
	public void iniciarPartida(Long idSalaJogo) {
		getGerenciadorSalasJogoEntrada().iniciarPartida(idSalaJogo);

	}

	protected Map<String, SOClienteEntrada> getClientesEntrada() {
		return clientesEntrada;
	}

	protected void setClientesEntrada(
			Map<String, SOClienteEntrada> clientesEntrada) {
		this.clientesEntrada = clientesEntrada;
	}

	protected SOControladorSistemaEntrada getControladorSistemaEntrada() {
		return controladorSistemaEntrada;
	}

	protected void setControladorSistemaEntrada(
			SOControladorSistemaEntrada controladorSistemaEntrada) {
		this.controladorSistemaEntrada = controladorSistemaEntrada;
	}

	protected SOGerenciadorSalasJogoEntrada getGerenciadorSalasJogoEntrada() {
		return gerenciadorSalasJogoEntrada;
	}

	protected void setGerenciadorSalasJogoEntrada(
			SOGerenciadorSalasJogoEntrada gerenciadorSalasJogoEntrada) {
		this.gerenciadorSalasJogoEntrada = gerenciadorSalasJogoEntrada;
	}

}
